package com.yft.dao.base;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.springframework.orm.hibernate3.HibernateAccessor;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.yft.entity.base.BaseEntityUtils;
import com.yft.entity.base.Pager;

public class BaseDao extends HibernateDaoSupport {
	public static String entityKey = "c";
	public BaseDao(){}
	@SuppressWarnings("unchecked")
	public BaseDao(SessionFactory sessionFactory,Class c){this.setSessionFactory(sessionFactory);	}
	private HibernateTemplate getBaseHibernateTemplate(){HibernateTemplate ht =getHibernateTemplate();
		ht.setEntityInterceptor(new DaoInterceptor());
		ht.setFlushMode(HibernateAccessor.FLUSH_AUTO);
		return ht;
	}
	private Session getBaseSession(){
		return this.getSessionFactory().openSession(new DaoInterceptor());
	}
	public Object addEntity(Object o) {
		return getBaseHibernateTemplate().save(o);
	}
	@SuppressWarnings("unchecked")
	public boolean saveAllEntity(List objects){
		if (objects!=null){
		this.getBaseHibernateTemplate().saveOrUpdateAll(objects);
		return true;
		}else return false;
	}
	public boolean saveOrUpdateEntity(Object ob){
		getBaseHibernateTemplate().saveOrUpdate(ob);
		return true;
	}
	@SuppressWarnings("unchecked")
	public boolean deleteEntity(Class c,Serializable id) {
		Object object = this.getEntity(c,id);
		return deleteEntityByObject(object);
	}
	public boolean deleteEntityByObject(Object object) {
		getHibernateTemplate().delete(object);
		return true;
	}
	@SuppressWarnings("unchecked")
	public boolean deleteAllEntity(Class c,String[] ids){
		List<Object> list = new ArrayList<Object>();
		for (String id:ids){
			list.add(this.getEntity(c,id));
		}
		return deleteEntityList(list);
	}
	
	@SuppressWarnings("unchecked")
	public boolean deleteEntityList(List list){
		if (list!=null){
		getHibernateTemplate().deleteAll(list);
		return true;
		}else return true;
	}
	
	
	public boolean updateEntity(Object ob, Serializable id) {
		Session session = getBaseSession();
		Transaction transaction = session.getTransaction();
		try{
			transaction.begin();
			Object object = session.load(ob.getClass(), id);
			com.yft.util.BeanUtils.copyProperties(object, ob);
			session.update(object);
			transaction.commit();
			session.flush();
			session.close();
		}catch(Exception ex){
			if (null!=transaction)transaction.rollback();
			session.flush();
			session.close();
		}
		return true;
	}
	public boolean updateEntity(Object ob){
		getBaseHibernateTemplate().update(ob);
		return true;
	}
	@SuppressWarnings("unchecked")
	public Object getEntity(Class c,Serializable id) {
		return getHibernateTemplate().get(c, id);
	}
	@SuppressWarnings("unchecked")
	public List getListPager(String queryString,Object object,Pager page){
		int start = 0;int end = 0;
		if (page!=null){
			String countQuery = "select count("+entityKey+") from "+StringUtils.substringAfter(queryString, "from ");
			int i = countQuery.indexOf(" order by ");
			if(i!=-1) countQuery = countQuery.substring(0,i);
			if (StringUtils.startsWithIgnoreCase(queryString,"select distinct")){
				String o = StringUtils.substringBetween(queryString, "select", "from").trim();
				countQuery = "select count("+o+") from "+ StringUtils.substringAfter(queryString, "from");
			}
			countQuery = countQuery.replaceAll(" fetch "," ");
			boolean isGroup = false;
			if(countQuery.indexOf(" group by where ")!=-1){
				countQuery = countQuery.replaceFirst(" group by where "," where ");
				queryString = queryString.replaceFirst(" group by where "," where ");
				countQuery += " group by " + entityKey;
				isGroup = true;
			}
			List<Long> countlist = getList(countQuery, object, 0, 0);
			if(countlist==null || countlist.size()==0){
				page.setRecordCount(0);
				return new ArrayList();
			}
			if(isGroup) page.setRecordCount(countlist.size());
			else{
				if(countlist.get(0)==null || countlist.get(0).intValue()==0){
					page.setRecordCount(0);
					return new ArrayList();
				}
				page.setRecordCount(countlist.get(0).intValue());
			}
			start = (page.getPage()<1)? 0 : (page.getPage()-1)* page.getPageSize();
			end = page.getPageSize();
		}else{
			if(queryString.indexOf(" group by where ")!=-1){
				queryString = queryString.replaceFirst(" group by where "," where ");
			}
		}
		List list = getList(queryString,object,start,end);
		return list;
	}
	
	@SuppressWarnings("unchecked")
	public List getList(final String queryString, final Object object, final int startPoint, final int endPoint) {
		List list = getHibernateTemplate().executeFind(new HibernateCallback() {
			public Object doInHibernate(Session session) {
				List list=new ArrayList();
				try {
					Query query = session.createQuery(queryString);
					if (object!=null) query.setProperties(object);
					if (startPoint>=0) query.setFirstResult(startPoint);
					if (endPoint>0) query.setMaxResults(endPoint);
					list= query.list();
					session.flush();
					session.close();
					return list;
				} catch (Exception e) {
					session.flush();
					session.close();
					return list;
				}
			}
		});
		return list;
	}
	

	public Object executeHql(final String sqlString) {
		Object object = getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session) {
				Query query = session.createQuery(sqlString);
				session.flush();
				session.close();
				return query.executeUpdate();
		}});
		return object;
	}
	public Object executeHqlWithProperties(final String sqlString, final Object condition) {
		Object object = getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session) {
				Query query = session.createQuery(sqlString);
				if (condition!=null) query.setProperties(condition);
				session.flush();
				session.close();
				return query.executeUpdate();
		}});
		return object;
	}
	public String parseSelectProperty(String[] propertys){
				String querString = "select "+entityKey+".count, ";
		for (String p:propertys){
			querString += entityKey+"."+p+",";
		}
		return StringUtils.substringBeforeLast(querString, ",")+" ";
		
	}
	
	public String needShowProperty(String[] propertys){
		String querString = "select ";
		for(int i =0;i<propertys.length;i++){
			if(i>0) querString += ",";
			querString += propertys[i];
		}
		return querString + " ";
		
	}
	
	@SuppressWarnings("unchecked")
	public List getGroupListPager(String entityKey,String queryString,Object object,Pager page){
		int start = 0;int end = 0;
		String countQuery = "select count("+entityKey+") from "+StringUtils.substringAfter(queryString, "from");
		List<Long> countlist = getList(countQuery, object, 0, 0);
		if (countlist==null || countlist.size()<1) return new ArrayList();
		if (page!=null){
			page.setRecordCount(countlist.size());
			start = (page.getPage()<1)? 0 : (page.getPage()-1)* page.getPageSize();
			end = page.getPageSize();
		}
		List list = getList(queryString,object,start,end);
		return list;
	}
	
	public boolean updateValues(Object obj,String str){
		return this.updateValuesHasWhere(obj, str,null);
	}
	
	public boolean updateValuesHasWhere(Object obj,String str,String whereStr){
		String hql = BaseEntityUtils.makeValues(obj,str,whereStr);
		if(hql==null) return false;
		Integer result =this.updateValuesHasHql(obj, hql);
		return result!=null && result.intValue()>0 ? true : false;
	}
	
	public Integer updateValuesHasHql(Object obj,String hql){
		Query query=getHibernateTemplate().getSessionFactory().getCurrentSession().createQuery(hql);
		query.setProperties(obj);
		return query.executeUpdate();
	}
}
